/**
 *  PODRendererScene.m
 *  PODRenderer
 *
 *  Created by ajit on 6/13/12.
 *  Copyright __MyCompanyName__ 2012. All rights reserved.
 */

#import "PODRendererScene.h"
#import "CC3PODResourceNode.h"
#import "CC3ActionInterval.h"
#import "CC3MeshNode.h"
#import "CC3Camera.h"
#import "CC3Light.h"


@implementation PODRendererScene

-(void) dealloc {
	[super dealloc];
}

/**
 * Constructs the 3D scene.
 *
 * Adds 3D objects to the scene, loading a 3D 'hello, world' message
 * from a POD file, and creating the camera and light programatically.
 *
 * When adapting this template to your application, remove all of the content
 * of this method, and add your own to construct your 3D model scene.
 *
 * NOTE: The POD file used for the 'hello, world' message model is fairly large,
 * because converting a font to a mesh results in a LOT of triangles. When adapting
 * this template project for your own application, REMOVE the POD file 'hello-world.pod'
 * from the Resources folder of your project!!
 */
-(void) initializeScene {

	// Create the camera, place it back a bit, and add it to the scene
	cameraNode = [CC3Camera nodeWithName: @"Camera"];
	cameraNode.location = cc3v( 0.0, 0.0, 6.0 );
	[self addChild: cameraNode];

	// Create a light, place it back and to the left at a specific
	// position (not just directional lighting), and add it to the scene
	lightNode = [CC3Light nodeWithName: @"Lamp"];
	lightNode.location = cc3v( 0.0, 0.0, 6.0 );
	lightNode.isDirectionalOnly = NO;
	[self addChild: lightNode];

	// This is the simplest way to load a POD resource file and add the
	// nodes to the CC3Scene, if no customized resource subclass is needed.
	[self addContentFromPODFile: @"hello-world.pod"];
	
	// Create OpenGL ES buffers for the vertex arrays to keep things fast and efficient,
	// and to save memory, release the vertex data in main memory because it is now redundant.
	[self createGLBuffers];
	[self releaseRedundantData];

	LogCleanDebug(@"The structure of this scene is: %@", [self structureDescription]);
	
    
    targetNode = (CC3MeshNode*)[self getNodeNamed: @"Hello"];
	
    
    // ------------------------------------------

	// But to add some dynamism, we'll animate the 'hello, world' message
	// using a couple of cocos2d actions...
	
	// Fetch the 'hello, world' 3D text object that was loaded from the
	// POD file and start it rotating
	
    /*CC3MeshNode* helloTxt = (CC3MeshNode*)[self getNodeNamed: @"Hello"];
	CCActionInterval* partialRot = [CC3RotateBy actionWithDuration: 1.0
														  rotateBy: cc3v(0.0, 30.0, 0.0)];
	[helloTxt runAction: [CCRepeatForever actionWithAction: partialRot]];*/
	
	// To make things a bit more appealing, set up a repeating up/down cycle to
	// change the color of the text from the original red to blue, and back again.
	
    /*GLfloat tintTime = 8.0f;
	ccColor3B startColor = helloTxt.color;
	ccColor3B endColor = { 50, 0, 200 };
	CCActionInterval* tintDown = [CCTintTo actionWithDuration: tintTime
														  red: endColor.r
														green: endColor.g
														 blue: endColor.b];
	CCActionInterval* tintUp = [CCTintTo actionWithDuration: tintTime
														red: startColor.r
													  green: startColor.g
													   blue: startColor.b];
	 CCActionInterval* tintCycle = [CCSequence actionOne: tintDown two: tintUp];
	[helloTxt runAction: [CCRepeatForever actionWithAction: tintCycle]];*/
}


#pragma mark Updating custom activity

/**
 * This template method is invoked periodically whenever the 3D nodes are to be updated.
 *
 * This method provides your app with an opportunity to perform update activities before
 * any changes are applied to the transformMatrix of the 3D nodes in the scene.
 *
 * For more info, read the notes of this method on CC3Node.
 */
-(void) updateBeforeTransform: (CC3NodeUpdatingVisitor*) visitor {}

/**
 * This template method is invoked periodically whenever the 3D nodes are to be updated.
 *
 * This method provides your app with an opportunity to perform update activities after
 * the transformMatrix of the 3D nodes in the scen have been recalculated.
 *
 * For more info, read the notes of this method on CC3Node.
 */
-(void) updateAfterTransform: (CC3NodeUpdatingVisitor*) visitor {}


#pragma mark Scene opening and closing

/**
 * Callback template method that is invoked automatically when the CC3Layer that
 * holds this scene is first displayed.
 *
 * This method is a good place to invoke one of CC3Camera moveToShowAllOf:... family
 * of methods, used to cause the camera to automatically focus on and frame a particular
 * node, or the entire scene.
 *
 * For more info, read the notes of this method on CC3Scene.
 */
-(void) onOpen {

	// Uncomment this line to have the camera move to show the entire scene.
	// This must be done after the CC3Layer has been attached to the view,
	// because this makes use of the camera frustum and projection.
//	[self.activeCamera moveWithDuration: 3.0 toShowAllOf: self];

	// Uncomment this line to draw the bounding box of the scene.
//	self.shouldDrawWireframeBox = YES;
}

/**
 * Callback template method that is invoked automatically when the CC3Layer that
 * holds this scene has been removed from display.
 *
 * For more info, read the notes of this method on CC3Scene.
 */
-(void) onClose {}


#pragma mark Handling touch events 

/**
 * This method is invoked from the CC3Layer whenever a touch event occurs, if that layer
 * has indicated that it is interested in receiving touch events, and is handling them.
 *
 * Override this method to handle touch events, or remove this method to make use of
 * the superclass behaviour of selecting 3D nodes on each touch-down event.
 *
 * This method is not invoked when gestures are used for user interaction. Your custom
 * CC3Layer processes gestures and invokes higher-level application-defined behaviour
 * on this customized CC3Scene subclass.
 *
 * For more info, read the notes of this method on CC3Scene.
 */
-(void) touchEvent: (uint) touchType at: (CGPoint) touchPoint {}

/**
 * This callback template method is invoked automatically when a node has been picked
 * by the invocation of the pickNodeFromTapAt: or pickNodeFromTouchEvent:at: methods,
 * as a result of a touch event or tap gesture.
 *
 * Override this method to perform activities on 3D nodes that have been picked by the user.
 *
 * For more info, read the notes of this method on CC3Scene.
 */
-(void) nodeSelected: (CC3Node*) aNode byTouchEvent: (uint) touchType at: (CGPoint) touchPoint {}



#pragma mark Custom Renderer Methods

- (void) moveTarget :(int) objectType :(int) direction :(float) movement {
    
    CC3Vector currentObjectLocation = targetNode.location;
    CC3Vector currentCameraLocation = cameraNode.location;
    CC3Vector currentLightLocation = lightNode.location;

    switch (objectType) {
        case 1:
            
            switch (direction) {
                case 1:
                    //UP Direction
                    currentObjectLocation.y += movement; 
                    break;
                    
                case 2:
                    //DOWN Direction
                    currentObjectLocation.y -= movement;
                    break;
                    
                case 3:
                    //LEFT Direction
                    currentObjectLocation.x -= movement;
                    break;
                    
                case 4:
                    //RIGHT Direction
                    currentObjectLocation.x += movement;
                    break;
                    
                case 5:
                    //IN Direction
                    currentObjectLocation.z -= movement;
                    break;
                    
                case 6:
                    //OUT Direction
                    currentObjectLocation.z += movement;
                    break;
                    
                default:
                    break;
            }
            
            [targetNode setLocation:currentObjectLocation];
            
            break;
            
        case 2:
            
            switch (direction) {
                case 1:
                    //UP Direction
                    currentCameraLocation.y += movement; 
                    break;
                    
                case 2:
                    //DOWN Direction
                    currentCameraLocation.y -= movement;
                    break;
                    
                case 3:
                    //LEFT Direction
                    currentCameraLocation.x -= movement;
                    break;
                    
                case 4:
                    //RIGHT Direction
                    currentCameraLocation.x += movement;
                    break;
                    
                case 5:
                    //IN Direction
                    currentCameraLocation.z -= movement;
                    break;
                    
                case 6:
                    //OUT Direction
                    currentCameraLocation.z += movement;
                    break;
                    
                default:
                    break;
            }
            
            [cameraNode setLocation:currentCameraLocation];
            
            break;
            
        case 3:
            
            switch (direction) {
                case 1:
                    //UP Direction
                    currentLightLocation.y += movement; 
                    break;
                    
                case 2:
                    //DOWN Direction
                    currentLightLocation.y -= movement;
                    break;
                    
                case 3:
                    //LEFT Direction
                    currentLightLocation.x -= movement;
                    break;
                    
                case 4:
                    //RIGHT Direction
                    currentLightLocation.x += movement;
                    break;
                    
                case 5:
                    //IN Direction
                    currentLightLocation.z -= movement;
                    break;
                    
                case 6:
                    //OUT Direction
                    currentLightLocation.z += movement;
                    break;
                    
                default:
                    break;
            }
            
            [lightNode setLocation:currentLightLocation];
            
            break;
            
        default:
            break;
    }
    
    
    
}

- (void) rotateTarget :(int) objectType :(int) direction :(float) movement {
    
    CC3Vector currentObjectRotation = targetNode.rotation;
    CC3Vector currentCameraRotation = cameraNode.rotation;
    CC3Vector currentLightRotation = lightNode.rotation;
    
    switch (objectType) {
        case 1:
            
            switch (direction) {
                case 1:
                    //UP Direction
                    currentObjectRotation.x -= movement;
                    break;
                    
                case 2:
                    //DOWN Direction
                    currentObjectRotation.x += movement;
                    break;
                    
                case 3:
                    //LEFT Direction
                    currentObjectRotation.y -= movement;
                    break;
                    
                case 4:
                    //RIGHT Direction
                    currentObjectRotation.y += movement;
                    break;
                    
                case 5:
                    //IN Direction
                    currentObjectRotation.z += movement;
                    break;
                    
                case 6:
                    //OUT Direction
                    currentObjectRotation.z -= movement;
                    break;
                    
                default:
                    break;
            }
            [targetNode setRotation:currentObjectRotation];
            
            break;
            
        case 2:
            
            switch (direction) {
                case 1:
                    //UP Direction
                    currentCameraRotation.x -= movement;
                    break;
                    
                case 2:
                    //DOWN Direction
                    currentCameraRotation.x += movement;
                    break;
                    
                case 3:
                    //LEFT Direction
                    currentCameraRotation.y -= movement;
                    break;
                    
                case 4:
                    //RIGHT Direction
                    currentCameraRotation.y += movement;
                    break;
                    
                case 5:
                    //IN Direction
                    currentCameraRotation.z += movement;
                    break;
                    
                case 6:
                    //OUT Direction
                    currentCameraRotation.z -= movement;
                    break;
                    
                default:
                    break;
            }
            [cameraNode setRotation:currentCameraRotation];
            
            break;
            
        case 3:
            
            switch (direction) {
                case 1:
                    //UP Direction
                    currentLightRotation.x -= movement;
                    break;
                    
                case 2:
                    //DOWN Direction
                    currentLightRotation.x += movement;
                    break;
                    
                case 3:
                    //LEFT Direction
                    currentLightRotation.y -= movement;
                    break;
                    
                case 4:
                    //RIGHT Direction
                    currentLightRotation.y += movement;
                    break;
                    
                case 5:
                    //IN Direction
                    currentLightRotation.z += movement;
                    break;
                    
                case 6:
                    //OUT Direction
                    currentLightRotation.z -= movement;
                    break;
                    
                default:
                    break;
            }
            [lightNode setRotation:currentLightRotation];
            
            break;
            
        default:
            break;
    
    }
    
}

- (void) updateLocation :(int) objectType :(UILabel*) lblX : (UILabel*) lblY : (UILabel*) lblZ  {
    
    switch (objectType) {
        case 1:
            
            [lblX setText:[NSString stringWithFormat:@"%2.2f", targetNode.location.x]];
            [lblY setText:[NSString stringWithFormat:@"%2.2f", targetNode.location.y]];
            [lblZ setText:[NSString stringWithFormat:@"%2.2f", targetNode.location.z]];
            
            break;
            
        case 2:
            
            [lblX setText:[NSString stringWithFormat:@"%2.2f", cameraNode.location.x]];
            [lblY setText:[NSString stringWithFormat:@"%2.2f", cameraNode.location.y]];
            [lblZ setText:[NSString stringWithFormat:@"%2.2f", cameraNode.location.z]];
            
            break;
            
        case 3:
            
            [lblX setText:[NSString stringWithFormat:@"%2.2f", lightNode.location.x]];
            [lblY setText:[NSString stringWithFormat:@"%2.2f", lightNode.location.y]];
            [lblZ setText:[NSString stringWithFormat:@"%2.2f", lightNode.location.z]];
            
            break;
            
        default:
            break;
    }
    
    
}

- (void) updateRotation :(int) objectType :(UILabel*) lblX : (UILabel*) lblY : (UILabel*) lblZ  {
    
    switch (objectType) {
        case 1:
            
            [lblX setText:[NSString stringWithFormat:@"%2.2f", targetNode.rotation.x]];
            [lblY setText:[NSString stringWithFormat:@"%2.2f", targetNode.rotation.y]];
            [lblZ setText:[NSString stringWithFormat:@"%2.2f", targetNode.rotation.z]];
            
            break;
            
        case 2:
            
            [lblX setText:[NSString stringWithFormat:@"%2.2f", cameraNode.rotation.x]];
            [lblY setText:[NSString stringWithFormat:@"%2.2f", cameraNode.rotation.y]];
            [lblZ setText:[NSString stringWithFormat:@"%2.2f", cameraNode.rotation.z]];            
            break;
            
        case 3:
            [lblX setText:[NSString stringWithFormat:@"%2.2f", lightNode.rotation.x]];
            [lblY setText:[NSString stringWithFormat:@"%2.2f", lightNode.rotation.y]];
            [lblZ setText:[NSString stringWithFormat:@"%2.2f", lightNode.rotation.z]];
            
            break;
            
        default:
            break;
    }
    
}

@end

